<template>
  <a-card class="general-card">
    <template #title>
      <component :is="titleIcon" style="font-size: 18px;" />
      {{ tableTitle }}
    </template>
    <template #extra>
      <a-space direction="vertical" :size="15" v-if="condition">
        <a-button type="text" @click="switchStatus">
          <template #icon>
            <component :is="conditionStatus ? 'icon-double-up' : 'icon-double-down'" />
          </template>
          {{ conditionStatus ? '展开' : '收起' }}
        </a-button>
      </a-space>
    </template>
    <a-form :model="formModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }" label-align="left">
      <a-grid :cols="4" :colGap="10" :rowGap="10" :collapsed="conditionStatus">
        <a-grid-item v-for="(item, idx) in condition" :key="idx">
          <a-form-item :field="item.field" :label="item.label">
            <a-input @change="queryProcessor(item.field, idx, formModel[item.field])" class="condition-input-pr0" v-bind="item" v-if="item.type === 'input'" :placeholder="item.place" v-model="formModel[item.field]" allow-clear>
              <template #suffix>
                <a-select style="width: 5.6rem;" :options="conditionOptions" v-model="selectMode[item.field]" default-value="=" @change="selectProcessor(item.field, idx, selectMode[item.field])" />
              </template>
            </a-input>
            <a-select v-else-if="item.type === 'select'" v-model="formModel[item.field]" :loading="selectLoading" v-bind="item" @change="selectHandler(item.field, idx, formModel[item.field])" @popup-visible-change="optionProcessor(item, idx)" :options="item.options.length > 0 ? item.options : asyncOptions[idx]" :placeholder="item.place" allow-clear allow-search />
            <a-range-picker v-else-if="item.type === 'DatePicker'" show-time v-bind="item" v-model="formModel[item.field]" @change="dateProcessor(item.field, idx, formModel[item.field])" format="YYYY-MM-DD HH:mm:ss" style="width: 100%" allow-clear />
          </a-form-item>
        </a-grid-item>
      </a-grid>
    </a-form>
    <a-divider style="margin-top: 0" />
    <a-row style="margin-bottom: 16px">
      <a-col :span="16">
        <a-space>
          <a-button v-if="isCreate" type="primary" @click="createHandler" v-permission="newActions.add.permission">
            <template #icon>
              <icon-plus />
            </template>
            新建
          </a-button>
          <a-upload v-if="isImport" action="/">
            <template #upload-button>
              <a-button>批量导入</a-button>
            </template>
          </a-upload>
        </a-space>
      </a-col>
      <a-col :span="8" style="text-align: right" v-if="isSearchBtnGroup">
        <a-button type="primary" @click="search">
          <template #icon>
            <icon-search />
          </template>
          查询
        </a-button>
        <a-button type="text" @click="reset">
          <template #icon>
            <icon-refresh />
          </template>
          重置
        </a-button>
        <a-button v-if="isExport">
          <template #icon>
            <icon-download />
          </template>
          下载
        </a-button>
        <a-popover position="br" trigger="click">
          <a-button type="text">
            <template #icon>
              <LineHeightIcon size="15" />
            </template>
            列
          </a-button>
          <template #content>
            <ColumnConfig :columns="columns" @on-sync-columns="onColumnsSyncHandler" />
          </template>
        </a-popover>
      </a-col>
    </a-row>
    <a-table row-key="id" :loading="loading" :pagination="isShowPagination ? pagination : isShowPagination" :default-expanded-keys="allKeys" :data="renderData" :bordered="false" :scroll="scroll" column-resizable sticky-header :selected-keys="selected" @row-click="selectionChange" :RowSelection="rowSelection" @pageChange="onPageChange">
      <template #columns>
        <span v-for="(item, idx) in pageColumnsConfig" :key="idx">
          <a-table-column v-if="!item.hide" :title="item.label" :data-index="item.field" tooltip ellipsis :slot-name="item.field" v-bind="item">
            <template #cell="{ record }">
              <slot :name="item.field" :row="record" :column="item">{{ record[item.field] }}</slot>
            </template>
          </a-table-column>
        </span>
        <a-table-column v-if="isOperation" title="操作" data-index="operations" :width="240">
          <template #cell="{ record }">
            <a-space>
              <slot name="firstOperation" :row="record" />
              <a-button size="small" type="primary" status="warning" @click="editHandler(record)" v-permission="newActions.edit.permission">编辑</a-button>
              <a-button size="small" type="primary" status="danger" @click="deleEventCallback(record)" v-permission="newActions.dele.permission">删除</a-button>
              <slot name="lastOperation" :row="record" />
            </a-space>
          </template>
        </a-table-column>
      </template>
    </a-table>
    <CustomDialog ref="dialog" :config="dialogConfig" @onRefresh="search">
      <template #dialog-content>
        <slot name="dialogContent" />
      </template>
    </CustomDialog>
  </a-card>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref, reactive, nextTick } from "vue";
import useLoading from "@/hooks/loading";
import CustomDialog from "@/components/custom-dialog/index.vue";
import { uniRequest } from "@/api/uni-apis";
import { Modal } from "@arco-design/web-vue";
import { Pagination } from "@/types/global";
import ColumnConfig from "./common/ColumnConfig.vue";
import { useMenuStore } from "@/store";

export default defineComponent({
  components: { CustomDialog, ColumnConfig },
  props: {
    //列表查询条件
    condition: {
      type: Object,
      default: undefined,
    },
    ///开启分页
    isShowPagination: {
      type: Boolean,
      default: true,
    },
    //是否显示新建按钮
    isCreate: {
      type: [Boolean, Number],
      default: false,
    },
    //是否显示导入按钮
    isImport: {
      type: [Boolean, Number],
      default: false,
    },
    //是否显示导出按钮
    isExport: {
      type: [Boolean, Number],
      default: false,
    },
    //列配置
    columns: {
      type: Array,
      default: () => {
        return [];
      },
    },
    //接口配置
    actions: {
      type: Object,
      default: () => {
        return {};
      },
    },
    //是否显示操作列
    isOperation: {
      type: Boolean,
      default: true,
    },
    //是否显示查询重置查询条件按钮组
    isSearchBtnGroup: {
      type: Boolean,
      default: true,
    },
    //列表标题
    tableTitle: {
      type: String,
      default: "",
    },
    //是否默认选中第零行
    defaultSelectedZeroRow: {
      type: [Boolean, Number],
      default: false,
    },
    //是否首次获取数据
    firstRefresh: {
      type: [Boolean, Number],
      default: true,
    },
    //传入查询参数以及额外表单数据
    parentQuery: {
      type: Object,
      default: () => {
        return undefined;
      },
    },
    //组件图标
    titleIcon: {
      type: String,
      default: "",
    },
    scroll: {
      type: Object,
      detault: () => {
        return {};
      },
    },
    //自带dialog默认配置
    dialogConfig: {
      type: Object,
      default: () => {
        return {
          width: "25vw",
          "mask-closable": false,
          draggable: true,
          title: "Title",
          titleIcon: "icon-file",
          formConfig: {
            itemLine: 1,
            formItem: [],
          },
        };
      },
    },
  },
  emits: ["onSelectRow"],
  setup(props, ctx) {
    const { loading, setLoading } = useLoading(false);
    const renderData = ref([]);
    const formModel = ref({});
    const queryMode = ref([]);
    const selectMode = ref({});
    const selected = ref([]);
    const deleteBtnStatus = ref(false);
    const selectLoading = ref(false);
    const allKeys = ref([]);
    const asyncOptions = ref([]);
    const conditionOptions = ref([
      { label: "精确", value: "=" },
      { label: "模糊", value: "like" },
    ]);
    const dialog = ref();
    const basePagination: Pagination = {
      page: 1,
      limit: 20,
      order: [],
      field: [],
    };
    const pageColumnsConfig = ref(props.columns);
    const conditionStatus = ref(true);
    const pagination = reactive({
      ...basePagination,
      pageSize: 20,
      showPageSize: true,
      simple: true, //简洁模式
    });

    const menuStore = useMenuStore();
    const newActions = ref(menuStore.dynamicConfigApi(props.actions));

    onMounted(async () => {
      if (props.firstRefresh) fetchData();
    });

    const recursionFindKeys = (arr: Array) => {
      arr.forEach((item) => {
        allKeys.value.push(item["id"]);
        if (item["children"] && item["children"].length) {
          recursionFindKeys(item["children"]);
        }
      });
    };

    const fetchData = async (params = { page: 1, limit: 20 }) => {
      setLoading(true);
      try {
        const res = await uniRequest(
          newActions.value.list.api,
          newActions.value.list.method,
          {
            ...basePagination,
            ...params,
          }
        );
        renderData.value = res?.data ?? res;
        if (renderData.value.some((item) => item.children)) {
          recursionFindKeys(renderData.value);
        }
        if (props.defaultSelectedZeroRow) {
          selectionChange(res.data[0]);
        }

        pagination.page = res.current_page || 1;
        pagination.total = res.total;
      } catch (err) {
        // you can report use errorHandler or other
      } finally {
        setLoading(false);
      }
    };

    const rowSelection = reactive({
      type: "radio",
      showCheckedAll: false,
      checkStrictly: true,
    });

    const search = () => {
      pagination.field = queryMode.value.filter((item) => item);
      fetchData({
        ...basePagination,
        ...pagination,
      });
    };
    const onPageChange = (page: number) => {
      fetchData({ ...basePagination, page });
    };

    /**
     * 显示更多查询条件/次要查询条件
     */
    const switchStatus = () => {
      conditionStatus.value = !conditionStatus.value;
    };
    /**
     * 删除回调
     */
    const deleEventCallback = ({ id }) => {
      Modal.warning({
        titleAlign: "start",
        title: "警告",
        content: "您确定要删除吗?",
        cancelText: "不了",
        hideCancel: false,
        okText: "删除",
        draggable: true,
        okLoading: deleteBtnStatus.value,
        simple: true,
        onOk: async () => {
          deleteBtnStatus.value = true;
          await uniRequest(
            newActions.value.dele?.api,
            newActions.value.dele?.method,
            { id }
          );
          search();
          deleteBtnStatus.value = false;
        },
      });
    };

    /**
     * 处理动态下拉框数据 查询条件类型为select如果未配置默认options并配有api接口将自动远程获取下拉列表数据
     */
    const optionProcessor = async (config, idx) => {
      selectLoading.value = true;
      if (config.api && (config.api !== "" || config.api !== null)) {
        if (asyncOptions.value.length > 0) {
          selectLoading.value = false;
          return;
        }
        nextTick(async () => {
          asyncOptions.value[idx] = (
            await uniRequest(config.api, "get", {})
          )?.data?.map((item) => {
            return { label: item.name, value: item.id };
          });
          selectLoading.value = false;
        });
      } else {
        selectLoading.value = false;
      }
    };

    /**
     * 查询条件处理
     */
    const queryProcessor = function (f, i, v) {
      queryMode.value[i] = v ? [f, "=", v] : undefined;
    };
    //匹配模式选择器
    const selectProcessor = function (f, i, v) {
      var arr = queryMode.value;
      arr.some((item) => item[0] === f)
        ? (queryMode.value[i][1] = v)
        : (queryMode.value[i] = [f, v, ""]);
    };
    const selectHandler = function (f, i, v) {
      queryMode.value[i] = v ? [f, "=", v] : undefined;
    };
    //date选择器
    const dateProcessor = function (f, i, v) {
      queryMode.value[i] = v ? [f, ">=", v[0]] : undefined;
      queryMode.value[i + 20] = v ? [f, "<=", v[1]] : undefined;
    };
    //行点击事件
    const selectionChange = function (row, ev) {
      selected.value[0] = row.id;
      ctx.emit("onSelectRow", row);
    };

    //存在父级参数时调用的刷新
    const onRefresh = function () {
      nextTick(() => {
        if (props.parentQuery) {
          queryMode.value[21] = [
            props.parentQuery.query.field,
            "=",
            props.parentQuery.query.value,
          ];
        }
        search();
      });
    };

    const createHandler = () => {
      const action = newActions.value.add;
      const obj = {};
      props.parentQuery &&
        Object.keys(props.parentQuery).forEach((key) => {
          const item = props.parentQuery[key];
          obj[item.field] = item.value;
        });
      dialog.value.show(action.title, action, obj);
    };

    const editHandler = (row) => {
      const action = newActions.value.edit;
      dialog.value.show(action.title, action, row);
    };

    const onColumnsSyncHandler = (columns) => {
      pageColumnsConfig.value = columns.value;
    };

    /**
     * 重置查询模型
     */
    const reset = () => {
      formModel.value = {};
      queryMode.value = [];
      onRefresh();
    };

    return {
      loading,
      renderData,
      pagination,
      pageColumnsConfig,
      formModel,
      allKeys,
      dialog,
      newActions,
      deleteBtnStatus,
      conditionStatus,
      rowSelection,
      selectLoading,
      asyncOptions,
      conditionOptions,
      selected,
      selectMode,
      search,
      onPageChange,
      reset,
      onRefresh,
      selectionChange,
      createHandler,
      selectHandler,
      dateProcessor,
      selectProcessor,
      queryProcessor,
      optionProcessor,
      deleEventCallback,
      switchStatus,
      editHandler,
      onColumnsSyncHandler,
    };
  },
});
</script>

<style scoped lang="less">
:deep(.arco-avatar) {
  vertical-align: text-bottom;
  background-color: unset;
  cursor: default;
  user-select: none;

  .arco-avatar-image {
    overflow: revert;
  }
}
.condition-input-pr0 {
  padding-right: 0;
}
:deep(.arco-table-th) {
  &:last-child {
    .arco-table-th-item-title {
      margin-left: 16px;
    }
  }
}
</style>

<style scoped>
.container >>> .arco-space-item {
  margin-bottom: 3px !important;
}
</style>
